Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(readr)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.3 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.2 ── Conflicts ────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(ggplot2)
library(highcharter)
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Attaching package: ‘magrittr’
The following object is masked from ‘package:purrr’:
set_names
The following object is masked from ‘package:tidyr’:
extract
EDA
Data loading
data <- read_csv("https://raw.githubusercontent.com/Alexburk93/Data_Wrangling_EDA/main/data/suicide_analysis.csv")
New names:Rows: 894 Columns: 22── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): Country name, Code, Indicator Name, Indicator Code, VAR, Variable, MEA, Measure, ISIC4...17, ISIC4...18, U...
dbl (9): Year, Age-standardized suicide rate - Sex: both sexes, Life Ladder, Social support, Healthy life expectanc...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Renaming variables and drop unwanted columns
# renaming the columns
data <- data %>%
rename(`Country_name` = `Country name`,
`Suicide_Rate` = `Age-standardized suicide rate - Sex: both sexes`,
`Life_ladder` = `Life Ladder`,
`Social_support` = `Social support`,
`Life_expectancy` = `Healthy life expectancy at birth`,
`Freedom_choices` = `Freedom to make life choices`,
`Corruption` = `Perceptions of corruption`,
`Indicator_name` = `Indicator Name`,
`Indicator_code` = `Indicator Code`)
# drop columns
# remove the original 'Time' column
data <- select(data, -Variable, -ISIC4...17, -ISIC4...18, -VAR, -MEA, -`Unit Code`)
data
Data exploration
# change names
names(data) <- make.names(names(data))
# dimensions of the dataframe
nrow(data)
[1] 894
[1] 16
[1] 894 16
# check the structure of the object
str(data)
tibble [894 × 16] (S3: tbl_df/tbl/data.frame)
$ Country_name : chr [1:894] "Australia" "Australia" "Australia" "Australia" ...
$ Code : chr [1:894] "AUS" "AUS" "AUS" "AUS" ...
$ Year : num [1:894] 2011 2011 2011 2011 2011 ...
$ Suicide_Rate : num [1:894] 10.1 10.1 10.1 10.1 11 ...
$ Life_ladder : num [1:894] 7.41 7.41 7.41 7.41 7.19 ...
$ Social_support : num [1:894] 0.967 0.967 0.967 0.967 0.954 ...
$ Life_expectancy: num [1:894] 72.3 72.3 72.3 72.3 72.1 ...
$ Freedom_choices: num [1:894] 0.945 0.945 0.945 0.945 0.935 ...
$ Corruption : num [1:894] 0.382 0.382 0.382 0.382 0.269 ...
$ Indicator_name : chr [1:894] "GDP (current US$)" "GDP (current US$)" "GDP (current US$)" "GDP (current US$)" ...
$ Indicator_code : chr [1:894] "NY.GDP.MKTP.CD" "NY.GDP.MKTP.CD" "NY.GDP.MKTP.CD" "NY.GDP.MKTP.CD" ...
$ GDP : num [1:894] 1.40e+12 1.40e+12 1.40e+12 1.40e+12 1.68e+11 ...
$ Measure : chr [1:894] "Index 2007=100" "Index 2007=100" "Index 2007=100" "Index 2007=100" ...
$ Unit : chr [1:894] "Index" "Index" "Index" "Index" ...
$ Value : num [1:894] 132 138 143 145 122 ...
$ Quarter : chr [1:894] "Q1" "Q2" "Q3" "Q4" ...
# look at columns 6, 7 and 10
head(data[ , c(2, 4:6, 12, 15)])
# look at columns 6, 7 and 10
tail(data[ , c(1, 3, 9)])
2011 2012 2013 2014 2015 2016 2017 2018 2019
100 100 100 100 100 100 100 97 97
data %>%
select(Country_name) %>%
unique() %>%
nrow()
[1] 19
unique(data$Country_name)
[1] "Australia" "New Zealand" "United States" "Spain" "Netherlands" "France"
[7] "Finland" "Belgium" "Japan" "South Africa" "Iceland" "Norway"
[13] "Sweden" "Italy" "Brazil" "United Kingdom" "Germany" "Canada"
[19] "Denmark"
[1] 2011 2012 2013 2014 2015 2016 2017 2018 2019
Interactive maps
# Set highcharter options for tooltip decimals
options(highcharter.tooltip.valueDecimals = 2)
# Create highcharter map visualization
hc <- highchart() %>%
hc_add_series_map(
worldgeojson, data, value = "GDP",
joinBy = c('name', 'Country_name'),
name = "GDP (current US$)"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "GDP in current US$")
hc
# Set highcharter options for tooltip decimals
options(highcharter.tooltip.valueDecimals = 2)
# Create map visualizations for each variable
hc_life_expectancy <- highchart() %>%
hc_add_series_map(
worldgeojson, data,
value = "Life_expectancy",
joinBy = c('name', 'Country_name'),
name = "Life Expectancy"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "Life Expectancy")
hc_suicide_rates <- highchart() %>%
hc_add_series_map(
worldgeojson, data,
value = "Suicide_Rate",
joinBy = c('name', 'Country_name'),
name = "Suicide Rates"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "Suicide Rate")
hc_corruption <- highchart() %>%
hc_add_series_map(
worldgeojson, data,
value = "Corruption",
joinBy = c('name', 'Country_name'),
name = "Corruption"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "Corruption")
# Display the map visualizations
list(hc_life_expectancy, hc_suicide_rates, hc_corruption)
[[1]]
[[2]]
[[3]]
NA
AVG GDP over years
Calculation
avg_gdp_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_gpd = mean(`GDP`))
avg_gdp_per_year
Plot
ggplot(avg_gdp_per_year, aes(x = Year, y = avg_gpd)) +
geom_line(color = "blue") +
labs(title = "Average GDP Over Time worldwide",
x = "Year",
y = "GDP") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_gdp_per_year$Year), max(avg_gdp_per_year$Year), by = 1))

AVG Happiness over years
Calculation
avg_happiness_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_happinnes = mean(`Life_ladder`, na.rm = T))
avg_happiness_per_year
Plot
ggplot(avg_happiness_per_year, aes(x = Year, y = avg_happinnes)) +
geom_line(color = "blue") +
labs(title = "Average Happiness Over Time worldwide",
x = "Year",
y = "Happiness") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_happiness_per_year$Year), max(avg_happiness_per_year$Year), by = 1))

AVG Suicide Rates over years
Calculation
avg_Suicide_Rate_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_Suicide_Rate = mean(`Suicide_Rate`, na.rm = T))
avg_Suicide_Rate_per_year
Plot
ggplot(avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate)) +
geom_line(color = "blue") +
labs(title = "Average Suicide Rate Over Time worldwide",
x = "Year",
y = "Suicide Rate") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_Suicide_Rate_per_year$Year), max(avg_Suicide_Rate_per_year$Year), by = 1))

AVG Bankruptcies over years
Calculation
avg_Bankruptcies_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_Bankruptcies = mean(`Value`, na.rm = T))
avg_Bankruptcies_per_year
Plot
ggplot(avg_Bankruptcies_per_year, aes(x = Year, y = avg_Bankruptcies)) +
geom_line(color = "blue") +
labs(title = "Average Bankruptcies Over Time worldwide",
x = "Year",
y = "Bankruptcies") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_Bankruptcies_per_year$Year), max(avg_Bankruptcies_per_year$Year), by = 1))

Plot Average GDP and Average Suicide Rate over years
# Finding the ratio for scaling the second axis
ratio <- max(avg_gdp_per_year$avg_gpd) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)
# Creating the base plot
ggplot() +
# Adding the bar plot for GDP
geom_bar(data = avg_gdp_per_year, aes(x = Year, y = avg_gpd), stat = "identity", fill = "skyblue", width = 0.2) +
# Adding the line plot for Average Happiness
geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 1.5) +
# Enhancing the plot
labs(title = "Average GDP and Suicide Rate Over Time",
x = "Year",
y = "Average GDP") +
scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(c(avg_gdp_per_year$Year, avg_Suicide_Rate_per_year$Year)),
max(c(avg_gdp_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

Plot Average Happinness and Average Suicide Rate over years
# Finding the ratio for scaling the second axis
ratio <- max(avg_happiness_per_year$avg_happinnes) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)
# Creating the base plot
ggplot() +
# Adding the bar plot for GDP
geom_bar(data = avg_happiness_per_year, aes(x = Year, y = avg_happinnes), stat = "identity", fill = "skyblue", width = 0.2) +
# Adding the line plot for Average Happiness
geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 1.5) +
# Enhancing the plot
labs(title = "Average Happinness and Suicide Rate Over Time",
x = "Year",
y = "Average Happinness") +
scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)),
max(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Plot Average Bankruptcies and Average Suicide Rate over years
# Finding the ratio for scaling the second axis
ratio <- max(avg_Bankruptcies_per_year$avg_Bankruptcies) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)
# Creating the base plot
ggplot() +
# Adding the bar plot for GDP
geom_bar(data = avg_Bankruptcies_per_year, aes(x = Year, y = avg_Bankruptcies), stat = "identity", fill = "skyblue", width = 0.2) +
# Adding the line plot for Average Happiness
geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 1.5) +
# Enhancing the plot
labs(title = "Average Bankruptcies and Suicide Rate Over Time",
x = "Year",
y = "Average Bankruptcies") +
scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(c(avg_Bankruptcies_per_year$Year, avg_Suicide_Rate_per_year$Year)),
max(c(avg_Bankruptcies_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Comparisions
Two Happiest and Two unhappiest countries vs average suicide
rate
avg_Suicide_Rate_per_country = data %>%
group_by(Country_name) %>%
summarise(avg_suicide_rate = mean(Suicide_Rate, na.rm = TRUE)) %>%
arrange(avg_suicide_rate) %>%
mutate(Row_Number = row_number())
avg_Suicide_Rate_per_country
avg_happiness_per_country <- data %>%
group_by(Country_name) %>%
summarise(avg_happiness = mean(Life_ladder, na.rm = TRUE)) %>%
arrange(desc(avg_happiness))
least_happy = tail(avg_happiness_per_country, 2)
most_happy = head(avg_happiness_per_country, 2)
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% least_happy$Country_name)
# Interpretation: Japan and South Africa are two very unhappy countries. And they also have a high suicide rate
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% most_happy$Country_name)
# Interpretation: Finland is a the second most happy country. But is still on place 16/19 when it comes to suicides
Two most wealthy countries and two most poor countries vs average
suicide rate
avg_gdp_per_country <- data %>%
group_by (`Country_name`) %>%
summarise(avg_gpd = mean(`GDP`)) %>%
arrange(desc(avg_gpd))
least_gdp = tail(avg_gdp_per_country, 2)
most_gdp = head(avg_gdp_per_country, 2)
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% least_gdp$Country_name)
# Interpretation: New Zealand and Iceland are two very small countries.
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% most_gdp$Country_name)
# Interpretation: The two biggest economies are based on the lower end of suicide rates
Two most bankcuptcies and two least bankcuptcies countries vs
average suicide rate
avg_Bankruptcies_per_year <- data %>%
group_by (`Country_name`) %>%
summarise(avg_bankruptcies = mean(`Value`, na.rm = T)) %>%
arrange(desc(avg_bankruptcies))
least_bank = tail(avg_Bankruptcies_per_year, 2)
most_bank = head(avg_Bankruptcies_per_year, 2)
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% least_bank$Country_name)
# Interpretation: Bankruptcies don't have an influence on suicide rates
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% most_bank$Country_name)
# Interpretation: Bankruptcies don't have an influence on suicide rates
In depth analysis Germany
Data preperation for Germany
# Prepare data for only Germany
germany_data = data %>%
filter(Country_name == "Germany")
Plot GDP Germany
# Plot Germany GDP over Years
avg_gdp_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_gdp = mean(GDP))
ggplot(avg_gdp_year_germany, aes(x = Year, y = avg_gdp)) +
geom_line(color = "blue") +
labs(title = "Average GPD Over Time - Germany",
x = "Year",
y = "GDP") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_gdp_year_germany$Year), max(avg_gdp_year_germany$Year), by = 1))

Plot Suicide Rate Germany
avg_suicide_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_suicide = mean(Suicide_Rate))
ggplot(avg_suicide_year_germany, aes(x = Year, y = avg_suicide)) +
geom_line(color = "blue") +
labs(title = "Average Suicide Rate Over Time - Germany",
x = "Year",
y = "Suicide Rate") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_suicide_year_germany$Year), max(avg_suicide_year_germany$Year), by = 1))

Plot Bankruptcies Rate Germany
avg_bank_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_bank = mean(Value))
ggplot(avg_bank_year_germany, aes(x = Year, y = avg_bank)) +
geom_line(color = "blue") +
labs(title = "Average bankruptcies Over Time - Germany",
x = "Year",
y = "Bankruptcies") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_bank_year_germany$Year), max(avg_bank_year_germany$Year), by = 1))

Plot Happiness Rate Germany
avg_happiness_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_happy = mean(Life_ladder))
ggplot(avg_happiness_year_germany, aes(x = Year, y = avg_happy)) +
geom_line(color = "blue") +
labs(title = "Average Happiness Over Time - Germany",
x = "Year",
y = "Happiness") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_happiness_year_germany$Year), max(avg_happiness_year_germany$Year), by = 1))

In depth analysis South Africa
Data preperation for South Africa
# Prepare data for only Germany
SA_data = data %>%
filter(Country_name == "South Africa")
Plot GDP SA
# Plot Germany GDP over Years
avg_gdp_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_gdp = mean(GDP))
ggplot(avg_gdp_year_SA, aes(x = Year, y = avg_gdp)) +
geom_line(color = "blue") +
labs(title = "Average GPD Over Time - SA",
x = "Year",
y = "GDP") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_gdp_year_SA$Year), max(avg_gdp_year_SA$Year), by = 1))

Plot Suicide Rate SA
avg_suicide_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_suicide = mean(Suicide_Rate))
ggplot(avg_suicide_year_SA, aes(x = Year, y = avg_suicide)) +
geom_line(color = "blue") +
labs(title = "Average Suicide Rate Over Time - SA",
x = "Year",
y = "Suicide Rate") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_suicide_year_SA$Year), max(avg_suicide_year_SA$Year), by = 1))

Plot Happiness Rate SA
avg_happiness_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_happy = mean(Life_ladder))
ggplot(avg_happiness_year_SA, aes(x = Year, y = avg_happy)) +
geom_line(color = "blue") +
labs(title = "Average Happiness Over Time - SA",
x = "Year",
y = "Happiness") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_happiness_year_SA$Year), max(avg_happiness_year_SA$Year), by = 1))

Plot Bankruptcies Rate SA
avg_bank_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_bank = mean(Value))
ggplot(avg_bank_year_SA, aes(x = Year, y = avg_bank)) +
geom_line(color = "blue") +
labs(title = "Average bankruptcies Over Time - SA",
x = "Year",
y = "Bankruptcies") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_bank_year_SA$Year), max(avg_bank_year_SA$Year), by = 1))

LS0tCnRpdGxlOiAiUHJlc2VudGF0aW9uIC0gRG9uJ3QgY29tbWl0IFN1aWNpZGUiCmF1dGhvcjogIk1hcmNrZW5yb2xkIENhZGV0ICYgQWxleGFuZGVyIEJ1cmtoYXJ0IgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgIGh0bWxfbm90ZWJvb2s6CiAgICAgICB0b2M6IHRydWUgCiAgICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgIHRvY19kZXB0aDogMgogICAgICAgdGhlbWU6IHVuaXRlZAogICAgICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGhpZ2hjaGFydGVyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpgYGAKIyBFREEKIyMgRGF0YSBsb2FkaW5nCmBgYHtyfQpkYXRhIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQWxleGJ1cms5My9EYXRhX1dyYW5nbGluZ19FREEvbWFpbi9kYXRhL3N1aWNpZGVfYW5hbHlzaXNfMi5jc3YiKQogICAgICAgICAgICAgICAgZGF0YSAlPiUgc2FtcGxlX24oMTkpCmBgYAojIyBSZW5hbWluZyB2YXJpYWJsZXMgYW5kIGRyb3AgdW53YW50ZWQgY29sdW1ucwpgYGB7cn0KIyByZW5hbWluZyB0aGUgY29sdW1ucyAKZGF0YSA8LSBkYXRhICU+JQogIHJlbmFtZShgQ291bnRyeV9uYW1lYCA9IGBDb3VudHJ5IG5hbWVgLAogICAgICAgICBgU3VpY2lkZV9SYXRlYCA9IGBBZ2Utc3RhbmRhcmRpemVkIHN1aWNpZGUgcmF0ZSAtIFNleDogYm90aCBzZXhlc2AsCiAgICAgICAgIGBMaWZlX2xhZGRlcmAgPSBgTGlmZSBMYWRkZXJgLAogICAgICAgICBgU29jaWFsX3N1cHBvcnRgID0gYFNvY2lhbCBzdXBwb3J0YCwKICAgICAgICAgYExpZmVfZXhwZWN0YW5jeWAgPSBgSGVhbHRoeSBsaWZlIGV4cGVjdGFuY3kgYXQgYmlydGhgLAogICAgICAgICBgRnJlZWRvbV9jaG9pY2VzYCA9IGBGcmVlZG9tIHRvIG1ha2UgbGlmZSBjaG9pY2VzYCwKICAgICAgICAgYENvcnJ1cHRpb25gID0gYFBlcmNlcHRpb25zIG9mIGNvcnJ1cHRpb25gLAogICAgICAgICBgSW5kaWNhdG9yX25hbWVgID0gYEluZGljYXRvciBOYW1lYCwKICAgICAgICAgYEluZGljYXRvcl9jb2RlYCA9IGBJbmRpY2F0b3IgQ29kZWApCgojIGRyb3AgY29sdW1ucyAKIyByZW1vdmUgdGhlIG9yaWdpbmFsICdUaW1lJyBjb2x1bW4KZGF0YSA8LSBzZWxlY3QoZGF0YSwgLVZhcmlhYmxlLCAtSVNJQzQuLi4xNywgLUlTSUM0Li4uMTgsIC1WQVIsIC1NRUEsIC1gVW5pdCBDb2RlYCkgIApkYXRhCmBgYAojIyBEYXRhIGV4cGxvcmF0aW9uCmBgYHtyfQpoZWFkKGRhdGEpCmBgYAoKYGBge3J9CiMgY2hhbmdlIG5hbWVzCm5hbWVzKGRhdGEpIDwtIG1ha2UubmFtZXMobmFtZXMoZGF0YSkpCmBgYAoKYGBge3J9CiMgZGltZW5zaW9ucyBvZiB0aGUgZGF0YWZyYW1lCm5yb3coZGF0YSkKbmNvbChkYXRhKQpkaW0oZGF0YSkKYGBgCgpgYGB7cn0KIyBjaGVjayB0aGUgc3RydWN0dXJlIG9mIHRoZSBvYmplY3QKc3RyKGRhdGEpCmBgYApgYGB7cn0KIyBsb29rIGF0IGNvbHVtbnMgNiwgNyBhbmQgMTAKaGVhZChkYXRhWyAsIGMoMiwgNDo2LCAxMiwgMTUpXSkKYGBgCgpgYGB7cn0KIyBsb29rIGF0IGNvbHVtbnMgNiwgNyBhbmQgMTAKdGFpbChkYXRhWyAsIGMoMSwgMywgOSldKQpgYGAKCmBgYHtyfQp0YWJsZShkYXRhJFllYXIpCmBgYAoKCmBgYHtyfQpkYXRhICU+JSAKICBzZWxlY3QoQ291bnRyeV9uYW1lKSAlPiUgCiAgdW5pcXVlKCkgJT4lIAogIG5yb3coKQpgYGAKCmBgYHtyfQp1bmlxdWUoZGF0YSRDb3VudHJ5X25hbWUpCmBgYAoKYGBge3J9CnVuaXF1ZShkYXRhJFllYXIpCmBgYAoKIyMgSW50ZXJhY3RpdmUgbWFwcwpgYGB7cn0KIyBTZXQgaGlnaGNoYXJ0ZXIgb3B0aW9ucyBmb3IgdG9vbHRpcCBkZWNpbWFscwpvcHRpb25zKGhpZ2hjaGFydGVyLnRvb2x0aXAudmFsdWVEZWNpbWFscyA9IDIpCgojIENyZWF0ZSBoaWdoY2hhcnRlciBtYXAgdmlzdWFsaXphdGlvbgpoYyA8LSBoaWdoY2hhcnQoKSAlPiUKICBoY19hZGRfc2VyaWVzX21hcCgKICAgIHdvcmxkZ2VvanNvbiwgZGF0YSwgdmFsdWUgPSAiR0RQIiwgCiAgICBqb2luQnkgPSBjKCduYW1lJywgJ0NvdW50cnlfbmFtZScpLAogICAgbmFtZSA9ICJHRFAgKGN1cnJlbnQgVVMkKSIKICApICAlPiUgCiAgaGNfY29sb3JBeGlzKHN0b3BzID0gY29sb3Jfc3RvcHMoKSkgJT4lIAogIGhjX3RpdGxlKHRleHQgPSAiV29ybGQgTWFwIikgJT4lIAogIGhjX3N1YnRpdGxlKHRleHQgPSAiR0RQIGluIGN1cnJlbnQgVVMkIikKCmhjCmBgYAoKYGBge3J9CiMgU2V0IGhpZ2hjaGFydGVyIG9wdGlvbnMgZm9yIHRvb2x0aXAgZGVjaW1hbHMKb3B0aW9ucyhoaWdoY2hhcnRlci50b29sdGlwLnZhbHVlRGVjaW1hbHMgPSAyKQoKIyBDcmVhdGUgbWFwIHZpc3VhbGl6YXRpb25zIGZvciBlYWNoIHZhcmlhYmxlCmhjX2xpZmVfZXhwZWN0YW5jeSA8LSBoaWdoY2hhcnQoKSAlPiUKICBoY19hZGRfc2VyaWVzX21hcCgKICAgIHdvcmxkZ2VvanNvbiwgZGF0YSwgCiAgICB2YWx1ZSA9ICJMaWZlX2V4cGVjdGFuY3kiLCAKICAgIGpvaW5CeSA9IGMoJ25hbWUnLCAnQ291bnRyeV9uYW1lJyksCiAgICBuYW1lID0gIkxpZmUgRXhwZWN0YW5jeSIKICApICU+JQogIGhjX2NvbG9yQXhpcyhzdG9wcyA9IGNvbG9yX3N0b3BzKCkpICU+JQogIGhjX3RpdGxlKHRleHQgPSAiV29ybGQgTWFwIikgJT4lCiAgaGNfc3VidGl0bGUodGV4dCA9ICJMaWZlIEV4cGVjdGFuY3kiKQoKaGNfc3VpY2lkZV9yYXRlcyA8LSBoaWdoY2hhcnQoKSAlPiUKICBoY19hZGRfc2VyaWVzX21hcCgKICAgIHdvcmxkZ2VvanNvbiwgZGF0YSwgCiAgICB2YWx1ZSA9ICJTdWljaWRlX1JhdGUiLCAKICAgIGpvaW5CeSA9IGMoJ25hbWUnLCAnQ291bnRyeV9uYW1lJyksCiAgICBuYW1lID0gIlN1aWNpZGUgUmF0ZXMiCiAgKSAlPiUKICBoY19jb2xvckF4aXMoc3RvcHMgPSBjb2xvcl9zdG9wcygpKSAlPiUKICBoY190aXRsZSh0ZXh0ID0gIldvcmxkIE1hcCIpICU+JQogIGhjX3N1YnRpdGxlKHRleHQgPSAiU3VpY2lkZSBSYXRlIikKCmhjX2NvcnJ1cHRpb24gPC0gaGlnaGNoYXJ0KCkgJT4lCiAgaGNfYWRkX3Nlcmllc19tYXAoCiAgICB3b3JsZGdlb2pzb24sIGRhdGEsIAogICAgdmFsdWUgPSAiQ29ycnVwdGlvbiIsIAogICAgam9pbkJ5ID0gYygnbmFtZScsICdDb3VudHJ5X25hbWUnKSwKICAgIG5hbWUgPSAiQ29ycnVwdGlvbiIKICApICU+JQogIGhjX2NvbG9yQXhpcyhzdG9wcyA9IGNvbG9yX3N0b3BzKCkpICU+JQogIGhjX3RpdGxlKHRleHQgPSAiV29ybGQgTWFwIikgJT4lCiAgaGNfc3VidGl0bGUodGV4dCA9ICJDb3JydXB0aW9uIikKCiMgRGlzcGxheSB0aGUgbWFwIHZpc3VhbGl6YXRpb25zCmxpc3QoaGNfbGlmZV9leHBlY3RhbmN5LCBoY19zdWljaWRlX3JhdGVzLCBoY19jb3JydXB0aW9uKQoKYGBgCgojIEFWRyBHRFAgb3ZlciB5ZWFycwojIyBDYWxjdWxhdGlvbiAKYGBge3J9CmF2Z19nZHBfcGVyX3llYXIgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkgKGBZZWFyYCkgJT4lIAogIHN1bW1hcmlzZShhdmdfZ3BkID0gbWVhbihgR0RQYCkpCgphdmdfZ2RwX3Blcl95ZWFyCmBgYAojIyBQbG90IApgYGB7cn0KZ2dwbG90KGF2Z19nZHBfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19ncGQpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR0RQIE92ZXIgVGltZSB3b3JsZHdpZGUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiR0RQIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19nZHBfcGVyX3llYXIkWWVhciksIG1heChhdmdfZ2RwX3Blcl95ZWFyJFllYXIpLCBieSA9IDEpKQpgYGAKIyBBVkcgSGFwcGluZXNzIG92ZXIgeWVhcnMKIyMgQ2FsY3VsYXRpb24gCmBgYHtyfQphdmdfaGFwcGluZXNzX3Blcl95ZWFyIDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgWWVhcmApICU+JSAKICBzdW1tYXJpc2UoYXZnX2hhcHBpbm5lcyA9IG1lYW4oYExpZmVfbGFkZGVyYCwgbmEucm0gPSBUKSkKCmF2Z19oYXBwaW5lc3NfcGVyX3llYXIKYGBgCiMjIFBsb3QgCgpgYGB7cn0KZ2dwbG90KGF2Z19oYXBwaW5lc3NfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19oYXBwaW5uZXMpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgSGFwcGluZXNzIE92ZXIgVGltZSB3b3JsZHdpZGUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiSGFwcGluZXNzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19oYXBwaW5lc3NfcGVyX3llYXIkWWVhciksIG1heChhdmdfaGFwcGluZXNzX3Blcl95ZWFyJFllYXIpLCBieSA9IDEpKQpgYGAKCiMgQVZHIFN1aWNpZGUgUmF0ZXMgb3ZlciB5ZWFycwojIyBDYWxjdWxhdGlvbiAKYGBge3J9CmF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkgKGBZZWFyYCkgJT4lIAogIHN1bW1hcmlzZShhdmdfU3VpY2lkZV9SYXRlID0gbWVhbihgU3VpY2lkZV9SYXRlYCwgbmEucm0gPSBUKSkKCmF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIKYGBgCiMjIFBsb3QgCgpgYGB7cn0KZ2dwbG90KGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19TdWljaWRlX1JhdGUpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSB3b3JsZHdpZGUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiU3VpY2lkZSBSYXRlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhciksIG1heChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpLCBieSA9IDEpKQpgYGAKIyBBVkcgQmFua3J1cHRjaWVzIG92ZXIgeWVhcnMKIyMgQ2FsY3VsYXRpb24gCmBgYHtyfQphdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyIDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgWWVhcmApICU+JSAKICBzdW1tYXJpc2UoYXZnX0JhbmtydXB0Y2llcyA9IG1lYW4oYFZhbHVlYCwgbmEucm0gPSBUKSkKCmF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIKYGBgCiMjIFBsb3QgCgpgYGB7cn0KZ2dwbG90KGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19CYW5rcnVwdGNpZXMpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgQmFua3J1cHRjaWVzIE92ZXIgVGltZSB3b3JsZHdpZGUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQmFua3J1cHRjaWVzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIkWWVhciksIG1heChhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyJFllYXIpLCBieSA9IDEpKQpgYGAKCiMgUGxvdCBBdmVyYWdlIEdEUCBhbmQgQXZlcmFnZSBTdWljaWRlIFJhdGUgb3ZlciB5ZWFycwpgYGB7cn0KIyBGaW5kaW5nIHRoZSByYXRpbyBmb3Igc2NhbGluZyB0aGUgc2Vjb25kIGF4aXMKcmF0aW8gPC0gbWF4KGF2Z19nZHBfcGVyX3llYXIkYXZnX2dwZCkgLyBtYXgoYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRhdmdfU3VpY2lkZV9SYXRlKQoKIyBDcmVhdGluZyB0aGUgYmFzZSBwbG90CmdncGxvdCgpICsKICAjIEFkZGluZyB0aGUgYmFyIHBsb3QgZm9yIEdEUAogIGdlb21fYmFyKGRhdGEgPSBhdmdfZ2RwX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfZ3BkKSwgc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIHdpZHRoID0gMC4yKSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgQXZlcmFnZSBIYXBwaW5lc3MKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19TdWljaWRlX1JhdGUgKiByYXRpbyksIGNvbG9yID0gInJlZCIsIHNpemUgPSAxLjUpICsKICAjIEVuaGFuY2luZyB0aGUgcGxvdAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBHRFAgYW5kIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQXZlcmFnZSBHRFAiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gcmF0aW8sIG5hbWUgPSAiQXZlcmFnZSBTdWljaWRlIFJhdGUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGMoYXZnX2dkcF9wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoYyhhdmdfZ2RwX3Blcl95ZWFyJFllYXIsIGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhcikpLCBieSA9IDEpKQoKYGBgCgojIFBsb3QgQXZlcmFnZSBIYXBwaW5uZXNzIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX2hhcHBpbmVzc19wZXJfeWVhciRhdmdfaGFwcGlubmVzKSAvIG1heChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJGF2Z19TdWljaWRlX1JhdGUpCgojIENyZWF0aW5nIHRoZSBiYXNlIHBsb3QKZ2dwbG90KCkgKwogICMgQWRkaW5nIHRoZSBiYXIgcGxvdCBmb3IgR0RQCiAgZ2VvbV9iYXIoZGF0YSA9IGF2Z19oYXBwaW5lc3NfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19oYXBwaW5uZXMpLCBzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIiwgd2lkdGggPSAwLjIpICsKICAjIEFkZGluZyB0aGUgbGluZSBwbG90IGZvciBBdmVyYWdlIEhhcHBpbmVzcwogIGdlb21fbGluZShkYXRhID0gYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX1N1aWNpZGVfUmF0ZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbm5lc3MgYW5kIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQXZlcmFnZSBIYXBwaW5uZXNzIikgKwogIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihjKGF2Z19oYXBwaW5lc3NfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGMoYXZnX2hhcHBpbmVzc19wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgYnkgPSAxKSkKCmBgYAoKIyBQbG90IEF2ZXJhZ2UgQmFua3J1cHRjaWVzIGFuZCBBdmVyYWdlIFN1aWNpZGUgUmF0ZSBvdmVyIHllYXJzCmBgYHtyfQojIEZpbmRpbmcgdGhlIHJhdGlvIGZvciBzY2FsaW5nIHRoZSBzZWNvbmQgYXhpcwpyYXRpbyA8LSBtYXgoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciRhdmdfQmFua3J1cHRjaWVzKSAvIG1heChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJGF2Z19TdWljaWRlX1JhdGUpCgojIENyZWF0aW5nIHRoZSBiYXNlIHBsb3QKZ2dwbG90KCkgKwogICMgQWRkaW5nIHRoZSBiYXIgcGxvdCBmb3IgR0RQCiAgZ2VvbV9iYXIoZGF0YSA9IGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19CYW5rcnVwdGNpZXMpLCBzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJza3libHVlIiwgd2lkdGggPSAwLjIpICsKICAjIEFkZGluZyB0aGUgbGluZSBwbG90IGZvciBBdmVyYWdlIEhhcHBpbmVzcwogIGdlb21fbGluZShkYXRhID0gYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX1N1aWNpZGVfUmF0ZSAqIHJhdGlvKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEuNSkgKwogICMgRW5oYW5jaW5nIHRoZSBwbG90CiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyBhbmQgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyByYXRpbywgbmFtZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYyhhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyJFllYXIsIGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhcikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChjKGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIGJ5ID0gMSkpCgpgYGAKCiMgQ29tcGFyaXNpb25zCgojIyBUd28gSGFwcGllc3QgYW5kIFR3byB1bmhhcHBpZXN0IGNvdW50cmllcyB2cyBhdmVyYWdlIHN1aWNpZGUgcmF0ZQpgYGB7cn0KYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSA9IGRhdGEgJT4lCiAgZ3JvdXBfYnkoQ291bnRyeV9uYW1lKSAlPiUKICBzdW1tYXJpc2UoYXZnX3N1aWNpZGVfcmF0ZSA9IG1lYW4oU3VpY2lkZV9SYXRlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcnJhbmdlKGF2Z19zdWljaWRlX3JhdGUpICU+JSAKICBtdXRhdGUoUm93X051bWJlciA9IHJvd19udW1iZXIoKSkKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkKCmF2Z19oYXBwaW5lc3NfcGVyX2NvdW50cnkgPC0gZGF0YSAlPiUKICBncm91cF9ieShDb3VudHJ5X25hbWUpICU+JQogIHN1bW1hcmlzZShhdmdfaGFwcGluZXNzID0gbWVhbihMaWZlX2xhZGRlciwgbmEucm0gPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShkZXNjKGF2Z19oYXBwaW5lc3MpKQoKbGVhc3RfaGFwcHkgPSAgdGFpbChhdmdfaGFwcGluZXNzX3Blcl9jb3VudHJ5LCAyKQptb3N0X2hhcHB5ID0gaGVhZChhdmdfaGFwcGluZXNzX3Blcl9jb3VudHJ5LCAyKQoKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBsZWFzdF9oYXBweSRDb3VudHJ5X25hbWUpCgojIEludGVycHJldGF0aW9uOiBKYXBhbiBhbmQgU291dGggQWZyaWNhIGFyZSB0d28gdmVyeSB1bmhhcHB5IGNvdW50cmllcy4gQW5kIHRoZXkgYWxzbyBoYXZlIGEgaGlnaCBzdWljaWRlIHJhdGUKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBtb3N0X2hhcHB5JENvdW50cnlfbmFtZSkKCiMgSW50ZXJwcmV0YXRpb246IEZpbmxhbmQgaXMgYSB0aGUgc2Vjb25kIG1vc3QgaGFwcHkgY291bnRyeS4gQnV0IGlzIHN0aWxsIG9uIHBsYWNlIDE2LzE5IHdoZW4gaXQgY29tZXMgdG8gc3VpY2lkZXMKCmBgYAoKIyMgVHdvIG1vc3Qgd2VhbHRoeSBjb3VudHJpZXMgYW5kIHR3byBtb3N0IHBvb3IgY291bnRyaWVzIHZzIGF2ZXJhZ2Ugc3VpY2lkZSByYXRlCmBgYHtyfQphdmdfZ2RwX3Blcl9jb3VudHJ5IDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgQ291bnRyeV9uYW1lYCkgJT4lIAogIHN1bW1hcmlzZShhdmdfZ3BkID0gbWVhbihgR0RQYCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYXZnX2dwZCkpCgpsZWFzdF9nZHAgPSAgdGFpbChhdmdfZ2RwX3Blcl9jb3VudHJ5LCAyKQptb3N0X2dkcCA9IGhlYWQoYXZnX2dkcF9wZXJfY291bnRyeSwgMikKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBsZWFzdF9nZHAkQ291bnRyeV9uYW1lKQoKIyBJbnRlcnByZXRhdGlvbjogTmV3IFplYWxhbmQgYW5kIEljZWxhbmQgYXJlIHR3byB2ZXJ5IHNtYWxsIGNvdW50cmllcy4gIAoKYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSAlaW4lIG1vc3RfZ2RwJENvdW50cnlfbmFtZSkKCiMgSW50ZXJwcmV0YXRpb246IFRoZSB0d28gYmlnZ2VzdCBlY29ub21pZXMgYXJlIGJhc2VkIG9uIHRoZSBsb3dlciBlbmQgb2Ygc3VpY2lkZSByYXRlcwpgYGAKCgojIyBUd28gbW9zdCBiYW5rY3VwdGNpZXMgYW5kIHR3byBsZWFzdCBiYW5rY3VwdGNpZXMgY291bnRyaWVzIHZzIGF2ZXJhZ2Ugc3VpY2lkZSByYXRlCmBgYHtyfQoKYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciA8LSBkYXRhICU+JSAKICBncm91cF9ieSAoYENvdW50cnlfbmFtZWApICU+JSAKICBzdW1tYXJpc2UoYXZnX2JhbmtydXB0Y2llcyA9IG1lYW4oYFZhbHVlYCwgbmEucm0gPSBUKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhhdmdfYmFua3J1cHRjaWVzKSkKCmxlYXN0X2JhbmsgPSAgdGFpbChhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCAyKQptb3N0X2JhbmsgPSBoZWFkKGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIsIDIpCgphdmdfU3VpY2lkZV9SYXRlX3Blcl9jb3VudHJ5ICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lICVpbiUgbGVhc3RfYmFuayRDb3VudHJ5X25hbWUpCgojIEludGVycHJldGF0aW9uOiBCYW5rcnVwdGNpZXMgZG9uJ3QgaGF2ZSBhbiBpbmZsdWVuY2Ugb24gc3VpY2lkZSByYXRlcwoKYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSAlaW4lIG1vc3RfYmFuayRDb3VudHJ5X25hbWUpCgojIEludGVycHJldGF0aW9uOiBCYW5rcnVwdGNpZXMgZG9uJ3QgaGF2ZSBhbiBpbmZsdWVuY2Ugb24gc3VpY2lkZSByYXRlcwpgYGAKIyBJbiBkZXB0aCBhbmFseXNpcyBHZXJtYW55CiMjIERhdGEgcHJlcGVyYXRpb24gZm9yIEdlcm1hbnkKYGBge3J9CiMgUHJlcGFyZSBkYXRhIGZvciBvbmx5IEdlcm1hbnkKZ2VybWFueV9kYXRhID0gZGF0YSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSA9PSAiR2VybWFueSIpCmBgYAoKIyMgUGxvdCBHRFAgR2VybWFueQpgYGB7cn0KIyBQbG90IEdlcm1hbnkgR0RQIG92ZXIgWWVhcnMKYXZnX2dkcF95ZWFyX2dlcm1hbnkgPSBnZXJtYW55X2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2dkcCA9IG1lYW4oR0RQKSkgCgoKZ2dwbG90KGF2Z19nZHBfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfZ2RwKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEdQRCBPdmVyIFRpbWUgLSBHZXJtYW55IiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkdEUCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfZ2RwX3llYXJfZ2VybWFueSRZZWFyKSwgbWF4KGF2Z19nZHBfeWVhcl9nZXJtYW55JFllYXIpLCBieSA9IDEpKQoKYGBgCgojIyBQbG90IFN1aWNpZGUgUmF0ZSBHZXJtYW55CmBgYHtyfQphdmdfc3VpY2lkZV95ZWFyX2dlcm1hbnkgPSBnZXJtYW55X2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX3N1aWNpZGUgPSBtZWFuKFN1aWNpZGVfUmF0ZSkpIAoKCmdncGxvdChhdmdfc3VpY2lkZV95ZWFyX2dlcm1hbnksIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19zdWljaWRlKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUgLSBHZXJtYW55IiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIlN1aWNpZGUgUmF0ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfc3VpY2lkZV95ZWFyX2dlcm1hbnkkWWVhciksIG1heChhdmdfc3VpY2lkZV95ZWFyX2dlcm1hbnkkWWVhciksIGJ5ID0gMSkpCmBgYAojIyBQbG90IEJhbmtydXB0Y2llcyBSYXRlIEdlcm1hbnkKYGBge3J9CmF2Z19iYW5rX3llYXJfZ2VybWFueSA9IGdlcm1hbnlfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfYmFuayA9IG1lYW4oVmFsdWUpKSAKCgpnZ3Bsb3QoYXZnX2JhbmtfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfYmFuaykpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBiYW5rcnVwdGNpZXMgT3ZlciBUaW1lIC0gR2VybWFueSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJCYW5rcnVwdGNpZXMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2JhbmtfeWVhcl9nZXJtYW55JFllYXIpLCBtYXgoYXZnX2JhbmtfeWVhcl9nZXJtYW55JFllYXIpLCBieSA9IDEpKQpgYGAKIyMgUGxvdCBIYXBwaW5lc3MgUmF0ZSBHZXJtYW55CmBgYHtyfQphdmdfaGFwcGluZXNzX3llYXJfZ2VybWFueSA9IGdlcm1hbnlfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfaGFwcHkgPSBtZWFuKExpZmVfbGFkZGVyKSkgCgoKZ2dwbG90KGF2Z19oYXBwaW5lc3NfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfaGFwcHkpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgSGFwcGluZXNzIE92ZXIgVGltZSAtIEdlcm1hbnkiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiSGFwcGluZXNzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19oYXBwaW5lc3NfeWVhcl9nZXJtYW55JFllYXIpLCBtYXgoYXZnX2hhcHBpbmVzc195ZWFyX2dlcm1hbnkkWWVhciksIGJ5ID0gMSkpCmBgYAojIEluIGRlcHRoIGFuYWx5c2lzIFNvdXRoIEFmcmljYQojIyBEYXRhIHByZXBlcmF0aW9uIGZvciBTb3V0aCBBZnJpY2EKYGBge3J9CiMgUHJlcGFyZSBkYXRhIGZvciBvbmx5IEdlcm1hbnkKU0FfZGF0YSA9IGRhdGEgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgPT0gIlNvdXRoIEFmcmljYSIpCmBgYAoKIyMgUGxvdCBHRFAgU0EKYGBge3J9CiMgUGxvdCBHZXJtYW55IEdEUCBvdmVyIFllYXJzCmF2Z19nZHBfeWVhcl9TQSA9IFNBX2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2dkcCA9IG1lYW4oR0RQKSkgCgoKCmdncGxvdChhdmdfZ2RwX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19nZHApKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR1BEIE92ZXIgVGltZSAtIFNBIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkdEUCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfZ2RwX3llYXJfU0EkWWVhciksIG1heChhdmdfZ2RwX3llYXJfU0EkWWVhciksIGJ5ID0gMSkpCgpgYGAKIyMgUGxvdCBTdWljaWRlIFJhdGUgU0EKYGBge3J9CmF2Z19zdWljaWRlX3llYXJfU0EgPSBTQV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19zdWljaWRlID0gbWVhbihTdWljaWRlX1JhdGUpKSAKCgpnZ3Bsb3QoYXZnX3N1aWNpZGVfeWVhcl9TQSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX3N1aWNpZGUpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIE92ZXIgVGltZSAtIFNBIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIlN1aWNpZGUgUmF0ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfc3VpY2lkZV95ZWFyX1NBJFllYXIpLCBtYXgoYXZnX3N1aWNpZGVfeWVhcl9TQSRZZWFyKSwgYnkgPSAxKSkKYGBgCgojIyBQbG90IEhhcHBpbmVzcyBSYXRlIFNBCmBgYHtyfQphdmdfaGFwcGluZXNzX3llYXJfU0EgPSBTQV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19oYXBweSA9IG1lYW4oTGlmZV9sYWRkZXIpKSAKCgpnZ3Bsb3QoYXZnX2hhcHBpbmVzc195ZWFyX1NBLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfaGFwcHkpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgSGFwcGluZXNzIE92ZXIgVGltZSAtIFNBIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkhhcHBpbmVzcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfaGFwcGluZXNzX3llYXJfU0EkWWVhciksIG1heChhdmdfaGFwcGluZXNzX3llYXJfU0EkWWVhciksIGJ5ID0gMSkpCmBgYAoKIyMgUGxvdCBCYW5rcnVwdGNpZXMgUmF0ZSBTQQpgYGB7cn0KYXZnX2JhbmtfeWVhcl9TQSA9IFNBX2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2JhbmsgPSBtZWFuKFZhbHVlKSkgCgoKZ2dwbG90KGF2Z19iYW5rX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19iYW5rKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIGJhbmtydXB0Y2llcyBPdmVyIFRpbWUgLSBTQSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJCYW5rcnVwdGNpZXMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2JhbmtfeWVhcl9TQSRZZWFyKSwgbWF4KGF2Z19iYW5rX3llYXJfU0EkWWVhciksIGJ5ID0gMSkpCmBgYA==